#include "client.h"
#include <openssl/md5.h>

void putsHandle(int clientfd,train_t * t)
{
    char pathname[1024] = {0};
    sprintf(pathname,"%s",t->buff);
    printf("pathname>%s<\n",pathname);
    int filefd = open(pathname,O_RDONLY);
    if(filefd == -1)
    {
        perror("open file");
    }
    
    char md5_result[33];
    md5_result[32] = '\0';
    get_md5(filefd,md5_result,33);
    send(clientfd,md5_result,33,0);
    int md5check;
    recv(clientfd,&md5check,sizeof(int),0);
    if(md5check == 1)
    {
        goto successful;
    }else if(md5check == -1)
    {
        printf("fail:filename already in pwd!\n");
        return;
    }


    struct stat filestat;
    int ret = fstat(filefd,&filestat);
    if(ret == -1)
    {
        perror("fstat");
    }
    int filesize = filestat.st_size;
    printf("fliesize:%d\n",filesize);
    sendn(clientfd,&filesize,sizeof(int));
    printf("sendn over\n");

    off_t offset;
    recvn(clientfd,&offset,sizeof(off_t));//接收已有文件偏移量
    printf("recv offset:%ld\n",offset);
    int size_after = filesize - offset;

    
    char *pMap = (char *)mmap(NULL,size_after,PROT_READ,MAP_SHARED,filefd,0);
    if(pMap)
    {
        printf("after mmap\n");
        send(clientfd,pMap=pMap+offset,size_after,0);
    }
    munmap(pMap,size_after);

successful:
    printf("send file successfully\n");
    close(filefd);
}




void getsHandle(int clientfd,train_t * t)
{
    int file_check;
    recv(clientfd,&file_check,sizeof(int),0);
    printf("file_check:%d\n",file_check);
    if(file_check == 0)
    {
        printf("check file name!\n");
        return;
    }
    printf("fileName:%s<\n",t->buff);
    char pathname[1024] = {0};
    sprintf(pathname,"./%s",t->buff);
    int filefd = open(pathname,O_RDWR|O_CREAT,0664);
    printf("after open\n");
    if(filefd == -1)
    {
        perror("open file");
    }

    struct stat filestat;
    int ret = fstat(filefd,&filestat);
    if(ret == -1)
    {
        perror("fstat");
    }

    int filesize;
    recv(clientfd,&filesize,sizeof(int),0);
    printf("recv filesize:%d\n",filesize);
    

    int currsize = filestat.st_size;
    printf("file currsize:%d\n",currsize);
    off_t offset = lseek(filefd,currsize,SEEK_SET);
    printf("offset:%ld\n",offset);
    sendn(clientfd,&offset,sizeof(off_t));//传已有文件偏移量
    
    char buffer[1024];
    memset(buffer,0,sizeof(buffer));
   
    int after_size =filesize-offset;
    printf("To be recv size:%d\n",after_size);
    ftruncate(filefd,filesize);

    char *pMap = (char *)mmap(NULL,after_size,PROT_READ|PROT_WRITE,MAP_SHARED,filefd,0);
    if(pMap)
    {
        printf("after mmap\n");
        if(after_size !=0)
        {
        recv(clientfd,pMap=pMap+offset,after_size,MSG_WAITALL);
        }
    }
    printf("recv file successfully\n");
    munmap(pMap,after_size);

    close(filefd);

}





void get_md5(int filefd,char md5_result[],int n)
{
    char buff[1000];
    int ret = 0;

    MD5_CTX ctx;
    MD5_Init(&ctx);
    while(1)
    {
        memset(buff,0,sizeof(buff));
        ret = read(filefd,buff,sizeof(buff));
        if(ret == 0)
        {
            break;
        }
        MD5_Update(&ctx,buff,ret);
    }
    unsigned char md[16] = {0};
    MD5_Final(md,&ctx);
    for(int i =0;i < 16;i++)
    {
        char frag[3] = {0};
        sprintf(frag,"%02x",md[i]);
        strcat(md5_result,frag);
        md5_result[32] = '\0';
    }
    
}

